Skip to content
标签
交互
字数
1102 字
阅读时间
5 分钟

一、概述

WebSocket 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助HTTP请求完成。 WebSocket是真正实现了全双工通信的服务器向客户端推的互联网技术。 它是一种在单个TCP连接上进行全双工通讯协议。Websocket通信协议与2011年倍IETF定为标准RFC 6455,Websocket API被W3C定为标准。

全双工和单工的区别?

  • 全双工(Full Duplex)是通讯传输的一个术语。通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指A→B的同时B→A,是瞬时同步的。

  • 单工、半双工(Half Duplex),所谓半双工就是指一个时间段内只有一个动作发生,举个简单例子,一条窄窄的马路,同时只能有一辆车通过,当目前有两辆车对开,这种情况下就只能一辆先过,等到头儿后另一辆再开,这个例子就形象的说明了半双工的原理。早期的对讲机、以及早期集线器等设备都是基于半双工的产品。随着技术的不断进步,半双工会逐渐退出历史舞台。

1.1 http和websocket的区别

http:http协议是短连接,因为请求之后,都会关闭连接,下次重新请求数据,需要再次打开链接。 websocket:WebSocket协议是一种长链接,只需要通过一次请求来初始化链接,然后所有的请求和响应都是通过这个TCP链接进行通讯。

二、使用示例

2.1 与springboot整合

依赖

xml
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

handler处理器

java
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
public class MyHandler extends TextWebSocketHandler {
	@Override
	public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
		System.out.println("获取到消息 >> " + message.getPayload());
		session.sendMessage(new TextMessage("消息已收到"));
		if(message.getPayload().equals("10")){
			for (int i = 0; i < 10; i++) {
				session.sendMessage(new TextMessage("消息 -> " + i));
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		session.sendMessage(new TextMessage("欢迎连接到ws服务"));
	}
	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		System.out.println("断开连接!");
	}
}

拦截器

java
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import java.util.Map;
@Component
public class MyHandshakeInterceptor implements HandshakeInterceptor {
    /**
    * 握手之前,若返回false,则不建立链接
    *
    * @param request
    * @param response
    * @param wsHandler
    * @param attributes
    * @return
    * @throws Exception
    */
	@Override
	public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
		//将用户id放入socket处理器的会话(WebSocketSession)中
		attributes.put("uid", 1001);
		System.out.println("开始握手。。。。。。。");
		return true;
	}
	@Override
	public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
		System.out.println("握手成功啦。。。。。。");
        // 连接成功后将连接信息存储,实现分布式调用。
	}
}

2.2 原生Demo

依赖

xml
<dependency>
	<groupId>javax</groupId>
	<artifactId>javaee-api</artifactId>
	<version>7.0</version>
	<scope>provided</scope>
</dependency>

代码

java
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
// 申明这是一个websocket服务
// 需要指定访问该服务的地址,在地址中可以指定参数,需要通过{}进行占位
@ServerEndpoint("/websocket/{uid}")
public class MyWebSocket {
    // 该方法将在建立连接后执行,会传入session对象,就是客户端与服务端建立的长连接通道通过@PathParam获取url申明中的参数
    @OnOpen
    public void onOpen(Session session, @PathParam("uid") String uid) throwsIOException {
        // 连接成功
        session.getBasicRemote().sendText(uid + ",你好,欢迎连接WebSocket!");
    }
    // 该方法是在连接关闭后执行
    @OnClose
    public void onClose() {
    	System.out.println(this + "关闭连接");
    }
    // - 该方法用于接收客户端发来的消息 message:发来的消息数据 session:会话对象(也是通道)
    @OnMessage
    public void onMessage(String message, Session session) throws IOException {
    	System.out.println("接收到消息:" + message);
        
        // 通过session进行发送。
    	session.getBasicRemote().sendText("消息已收到.");
    }
    @OnError
    public void onError(Session session, Throwable error) {
    	System.out.println("发生错误");
    	error.printStackTrace();
    }
}

配置类

java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
	@Autowired
	private MyHandshakeInterceptor myHandshakeInterceptor;
	@Override
	public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		registry.addHandler(myHandler(), "/ws").setAllowedOrigins("*")
            // 添加拦截器
            .addInterceptors(this.myHandshakeInterceptor);
	}
	@Bean
	public WebSocketHandler myHandler() {
        // 添加处理器
		return new MyHandler();
	}
}